package lz.controls
{
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.MouseEvent;
	
	import lz.controls.events.SliderEvent;

	/**
	 * slider component
	 * @author lxh
	 * 
	 */	
	public class Slider extends EventDispatcher
	{
		private var _view :MovieClip;
		
		private var sliderThumbBtn :SimpleButton;
		private var sliderTrackFlag :MovieClip;
		private var sliderTrack	:MovieClip;
		
		protected var _minimum:Number = 0;
		protected var _maximum:Number = 10;
		protected var _value:Number = 0;
		protected var _snapInterval:Number = 0;
		protected var _liveDragging :Boolean;
		protected var _width :Number;
		
		public function Slider()
		{
		}
		
		public function set view(value :DisplayObject):void
		{
			_view = value as MovieClip;
			//
			configUI();
		}
		
		public function get view():DisplayObject
		{
			return _view;
		}
		
		protected function configUI():void 
		{
			if(_view == null)
			{
				return;
			}
			sliderThumbBtn = _view.sliderThumbBtn;
			sliderTrack = _view.sliderTrack;
			sliderTrackFlag = _view.sliderTrackFlag;
			sliderTrackFlag.mouseEnabled = false;
			sliderTrackFlag.mouseChildren = false;
			_width = sliderTrack.width;
			_minimum = 0;
			_maximum = _width - sliderThumbBtn.width;
			sliderThumbBtn.x = _maximum;
			_snapInterval = 1;
			//
			sliderThumbBtn.addEventListener(MouseEvent.MOUSE_DOWN,thumbPressHandler,false,0,true);
			sliderTrack.addEventListener(MouseEvent.CLICK,onTrackClick,false,0);
		}
		
		public function get minimum():Number 
		{ 
			return _minimum; 
		}
		public function set minimum(value:Number):void 
		{
			_minimum = value;
			this.value = Math.max(value, this.value);
		}
		
		public function get maximum():Number
		{
			return _maximum;
		}	
		
		public function set maximum(value:Number):void 
		{
			_maximum = value;
			this.value = Math.min(value, this.value);
		}
		
		public function get snapInterval():Number 
		{
			return _snapInterval;
		}
		
		public function set snapInterval(value:Number):void 
		{
			_snapInterval = value;
		}
		
		public function get value():Number 
		{
			return _value;
		}
		
		public function set value(value:Number):void 
		{
			doSetValue(value);
		}
		
		public function set liveDragging(value:Boolean):void 
		{
			_liveDragging = value;
		}		
		public function get liveDragging():Boolean 
		{
			return _liveDragging;
		}
		
		protected function doSetValue(val:Number, interactionType:String=null, clickTarget:String=null, keyCode:int=undefined):void 
		{
			var oldVal:Number = _value;
			if (_snapInterval != 0 && _snapInterval != 1)
			{ 
				var pow:Number = Math.pow(10, getPrecision(snapInterval));
				var snap:Number = _snapInterval * pow;
				var rounded:Number = Math.round(val * pow);
				var snapped:Number = Math.round(rounded / snap) * snap;
				var val:Number = snapped / pow;
				_value = Math.max(minimum, Math.min(maximum,val));
			} else 
			{
				_value = Math.max(minimum, Math.min(maximum, Math.round(val)));
			}
			if (oldVal != _value )
			{
				dispatchEvent(new SliderEvent(SliderEvent.CHANGE, value, clickTarget, interactionType, keyCode));
			}
			positionThumb();
		}
		protected function positionThumb():void 
		{
			sliderThumbBtn.x = maximum - value;
			sliderTrackFlag.width = maximum - value + sliderThumbBtn.width/2;
		}
		protected function getPrecision(num:Number):Number 
		{
			var s:String = num.toString();
			if (s.indexOf(".") == -1) { return 0; }
			return s.split(".").pop().length;
		}
		
		protected function thumbPressHandler(event:MouseEvent):void 
		{
			_view.stage.addEventListener(MouseEvent.MOUSE_MOVE,doDrag,false,0,true);
			_view.stage.addEventListener(MouseEvent.MOUSE_UP,thumbReleaseHandler,false,0,true);
			dispatchEvent(new SliderEvent(SliderEvent.THUMB_PRESS, value,"", ""));
		}
		
		protected function thumbReleaseHandler(event:MouseEvent):void 
		{
			_view.stage.removeEventListener(MouseEvent.MOUSE_MOVE,doDrag);
			_view.stage.removeEventListener(MouseEvent.MOUSE_UP,thumbReleaseHandler);
			dispatchEvent(new SliderEvent(SliderEvent.THUMB_RELEASE, value, "", ""));
			dispatchEvent(new SliderEvent(SliderEvent.CHANGE, value,"", ""));
		}
		
		protected function onTrackClick(event:MouseEvent):void
		{			
			calculateValue(sliderTrack.mouseX, "", "");
			if (!liveDragging) 
			{
				dispatchEvent(new SliderEvent(SliderEvent.CHANGE, value, "", ""));
			}
		}
		
		protected function calculateValue(pos:Number, interactionType:String, clickTarget:String, keyCode:int = undefined):void
		{
			var newValue:Number = (pos/_width)*(maximum-minimum);
			newValue = (maximum - newValue);
			doSetValue(newValue, interactionType, clickTarget, keyCode);
		}
		
		protected function doDrag(event:MouseEvent):void 
		{
			var dist:Number = _width/snapInterval;
			var thumbPos:Number = sliderTrack.mouseX;
			calculateValue(thumbPos, "", "");
			dispatchEvent(new SliderEvent(SliderEvent.THUMB_DRAG, value, "", ""));
		}
	}
}